package com.ruoyi.framework.web.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.UserType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.user.CaptchaException;
import com.ruoyi.common.exception.user.CaptchaExpireException;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.ip.Address;
import com.ruoyi.common.utils.ip.AddressUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.security.SmsCodeAuthenticationToken;
import com.ruoyi.oss.cloud.OSSFactory;
import com.ruoyi.pay.domain.PayCoinUserForm;
import com.ruoyi.pay.service.IPayCoinCashService;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.form.LoginForm;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.wq.domain.WqNoticeChat;
import com.ruoyi.wq.domain.WqUserFriendForm;
import com.ruoyi.wq.service.IWqDynamicService;
import com.ruoyi.wq.service.IWqNoticeChatService;
import com.ruoyi.wq.service.IWqUserFriendService;
import com.ruoyi.wx.domain.DyMaForm;
import com.ruoyi.wx.domain.DyMaUser;
import com.ruoyi.wx.domain.WxApp;
import com.ruoyi.wx.domain.WxMaForm;
import com.ruoyi.wx.domain.WxMaMsgForm;
import com.ruoyi.wx.domain.WxMaUser;
import com.ruoyi.wx.domain.WxMpMsgForm;
import com.ruoyi.wx.service.DyMaUserService;
import com.ruoyi.wx.service.IWxAppService;
import com.ruoyi.wx.service.WxMaCodeService;
import com.ruoyi.wx.service.WxMaUserService;
import com.ruoyi.wx.service.WxMsgService;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;

/**
 * 登录校验方法
 * 
 * @author ruoyi
 */
@Component
public class SysLoginService {
	
    @Autowired
    private TokenService tokenService;

    @Resource
    private AuthenticationManager authenticationManager;

    @Autowired
    private RedisCache redisCache;
    
    @Autowired
    private ISysUserService userService;
    
    @Autowired
    private ISysConfigService sysConfigService;

    @Autowired
    private ISysConfigService configService;
    
    @Autowired
    private WxMaUserService wxMaUserService;
    
    @Autowired
    private WxMaCodeService wxMaCodeService;
    
    @Autowired
    private DyMaUserService dyMaUserService;
    
    @Autowired
    private IWxAppService wxAppService;
    
    @Autowired
    private IWqUserFriendService wqUserFriendService;
    
    @Autowired
    private IWqDynamicService wqDynamicService;
    
    @Autowired
    private UserVisitService userVisitService;
    
    @Autowired
	private IPayCoinCashService payCoinCashService;
    
    @Autowired
    private WxMsgService wxMsgService;
    
    @Autowired
    private CoinUserService coinUserService;
    
    @Autowired
    private IWqNoticeChatService wqNoticeChatService;
    
    public final static String KEY_USER = "key:user:";
    
    public final static String KEY_USER_TOTAL = "key:user:total";

    /**
     * 登录验证
     * 
     * @param username 用户名
     * @param password 密码
     * @param code 验证码
     * @param uuid 唯一标识
     * @return 结果
     */
    public String login(String username, String password, String code, String uuid)
    {
        boolean captchaOnOff = configService.selectCaptchaOnOff();
        // 验证码开关
        if (captchaOnOff)
        {
            validateCaptcha(username, code, uuid);
        }
        // 用户验证
        Authentication authentication = null;
        try
        {
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager
                    .authenticate(new UsernamePasswordAuthenticationToken(username, password));
        }
        catch (Exception e)
        {
            if (e instanceof BadCredentialsException)
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
                throw new UserPasswordNotMatchException();
            }
            else
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
                throw new ServiceException(e.getMessage());
            }
        }
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        recordLoginInfo(loginUser.getUserId());
        // 生成token
        return tokenService.createToken(loginUser);
    }

    /**
     * 校验验证码
     * 
     * @param username 用户名
     * @param code 验证码
     * @param uuid 唯一标识
     * @return 结果
     */
    public void validateCaptcha(String username, String code, String uuid)
    {
        String verifyKey = Constants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
        String captcha = redisCache.getCacheObject(verifyKey);
        redisCache.deleteObject(verifyKey);
        if (captcha == null)
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
            throw new CaptchaExpireException();
        }
        if (!code.equalsIgnoreCase(captcha))
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
            throw new CaptchaException();
        }
    }
    
    /**
     * 记录登录信息
     *
     * @param userId 用户ID
     */
    public void recordLoginInfo(Long userId)
    {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
        sysUser.setLoginDate(DateUtils.getNowDate());
        userService.updateUserProfile(sysUser);
    }

	public R<?> phoneLogin(LoginForm form) {
        // 验证码开关
		validateCaptcha(form.getPhone(), form.getCode(), form.getIv());
		userService.saveUserByPhone(form.getPhone());
        // 用户验证
        Authentication authentication = null;
        try
        {
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager
                    .authenticate(new SmsCodeAuthenticationToken(form.getPhone()));
        }
        catch (Exception e)
        {
            if (e instanceof BadCredentialsException)
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(form.getPhone(), Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
                throw new UserPasswordNotMatchException();
            }
            else
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(form.getPhone(), Constants.LOGIN_FAIL, e.getMessage()));
                throw new ServiceException(e.getMessage());
            }
        }
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(form.getPhone(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        recordLoginInfo(loginUser.getUserId());
        // 生成token
        String token = tokenService.createToken(loginUser);
        AjaxResult succes = AjaxResult.success();
        succes.put(Constants.ACCESS_TOKEN, token);
        succes.put("userId", loginUser.getUserId());
        succes.put("isWelcome", loginUser.getUser().getIsWelcome());
        return R.ok(succes);
	}

	public R<?> wxLogin(LoginForm form) {
		if(StringUtils.isNotBlank(form.getAppId()) && StringUtils.isNotBlank(form.getAppSecret())){
			// 新增配置
			configService.addConfig(form);
			
			WxApp app = new WxApp();
			app.setAppId(form.getAppId());
			app.setAppSecret(form.getAppSecret());
			app.setMchId(form.getMchId());
			app.setMchKey(form.getMchKey());
			app.setAppName(form.getAppName());
			app.setOneTemplateId(form.getOneTemplateId());
			wxAppService.addWxApp(app);
		}
		
		WxMaForm wxMaForm = new WxMaForm();
		wxMaForm.setAppId(form.getAppId());
		wxMaForm.setCode(form.getCode());
		wxMaForm.setEncryptedData(form.getEncryptedData());
		wxMaForm.setIv(form.getIv());
		wxMaForm.setRawData(form.getRawData());
		wxMaForm.setSignature(form.getSignature());
		WxMaUser wxMaUser = wxMaUserService.getUserInfo(wxMaForm);
		
		WxApp app = wxAppService.getByAppid(wxMaUser.getAppId());
		Date now = new Date();
		if(now.compareTo(app.getExpireTime()) > 0){
			throw new ServiceException("授权已过期");
		}
		
		Address address = AddressUtils.getAddressByIP();
		String friendId = RandomUtil.randomNumbers(11);
		// 注册用户
		SysUser user = new SysUser();
		
		SysUser otherUser = null;
		if(StringUtils.isNotBlank(wxMaUser.getUnionId()) && StringUtils.isNotBlank(app.getWxId())){
			List<SysUser> userList = userService.getUserNotNullByUnionId(app.getWxId(), wxMaUser.getUnionId());
			if(!CollectionUtils.isEmpty(userList)){
				otherUser = userList.get(0);
			}
		}
		user.setFriendId(Long.valueOf(friendId));
		user.setAppId(wxMaUser.getAppId());
		user.setOpenId(wxMaUser.getOpenId());
		user.setWxId(app.getWxId());
		user.setUnionId(wxMaUser.getUnionId());
		user.setDeptId(100L);
		SysUser randomUser = null;

		randomUser = userService.getRandomUser();
		while("微信用户".equals(randomUser.getNickName())){
			randomUser = userService.getRandomUser();
		}
		
		user.setNickName(randomUser.getNickName());
		user.setAvatar(randomUser.getAvatar());
		
		user.setUserType(UserType.APP.getCode());
		user.setLat(address.getLat());
		user.setLon(address.getLng());
		user.setProvince(address.getProvince());
		user.setCity(address.getCity());
		user.setDistrict(address.getDistrict());
		user.setToken(IdUtils.fastUUID());
		
		SysUser sysUser = userService.selectUserByOpenId(user.getOpenId());
		SysUser shareUser = null;
		if(StringUtils.isNotBlank(form.getShareUserId())){
			if("11605157".equals(form.getShareUserId())){
				// 管理员邀请
				user.setIsWelcome(1);
			}
			shareUser = userService.getById(form.getShareUserId());
		}
		if(sysUser == null){
			user.setScene(form.getScene());
			user.setPhonenumber(form.getPhone());
			
			// 自动注册
			if(shareUser != null){
				user.setVisitUserId(shareUser.getUserId());
			}
			
			user.setIsPay("1");
			if(otherUser != null){
				user.setWxOpenId(otherUser.getWxOpenId());
				user.setNickName(otherUser.getNickName());
				user.setIdCardStatus(otherUser.getIdCardStatus());
				user.setAvatar(otherUser.getAvatar());
				user.setSex(otherUser.getSex());
				user.setAge(otherUser.getAge());
				user.setWechat(otherUser.getWechat());
				user.setWechatStatus(otherUser.getWechatStatus());
				user.setAlbums(otherUser.getAlbums());
				if(otherUser.getPayNum() >= 10){
					user.setPayNum(10);
				}
				user.setIsWelcome(1);
				user.setPhonenumber(otherUser.getPhonenumber());
				user.setIsBlack(otherUser.getIsBlack());
				user.setStatus(otherUser.getStatus());
			}
			// 赠送会员
			if("1".equals(app.getStatus())){
				Date vipStartTime = new Date();
				Date vipEndTime = DateUtil.offsetDay(vipStartTime, 1);
				user.setWechatNum(10);
				user.setPublishNum(3);
				user.setVipStartTime(vipStartTime);
				user.setVipEndTime(vipEndTime);
			}
			
			userService.save(user);
			
			// 通过好友邀请注册，赠送趣币
			if(shareUser != null){
				
				// 赠送一天会员
				/*Date vipStartTime = new Date();
				Date vipEndTime = DateUtil.offsetDay(vipStartTime, 1);
				user.setWechatNum(10);
				user.setPublishNum(3);
				user.setVipStartTime(vipStartTime);
				user.setVipEndTime(vipEndTime);
				userService.updateById(user);*/
				
				/*PayCoinUserForm payCoinUserForm = new PayCoinUserForm();
		    	payCoinUserForm.setCoinNum(500);
		    	payCoinUserForm.setCoinType("0");
		    	payCoinUserForm.setRemark("邀请奖励");
		    	payCoinUserForm.setUserId(user.getUserId());
		    	coinUserService.savePayCoinUser(payCoinUserForm);*/
				
				// 赠送一天会员
				/*shareUser.setWechatNum(10);
				shareUser.setPublishNum(3);
				if(shareUser.getVipStartTime() == null){
					shareUser.setVipStartTime(vipStartTime);
				}
				if(shareUser.getVipEndTime() == null){
					shareUser.setVipEndTime(vipEndTime);
				}else{
					vipEndTime = DateUtil.offsetDay(shareUser.getVipEndTime(), 1);
					shareUser.setVipEndTime(vipEndTime);
				}*/
		    	
				/*PayCoinUserForm payCoinUserForm = new PayCoinUserForm();
		    	payCoinUserForm.setCoinNum(500);
		    	payCoinUserForm.setCoinType("0");
		    	payCoinUserForm.setRemark("邀请奖励");
		    	payCoinUserForm.setUserId(shareUser.getUserId());
		    	coinUserService.savePayCoinUser(payCoinUserForm);*/
				
			}
			
			// 需要关注公众号送奖励
			/*SysConfig config = sysConfigService.getConfig(user.getAppId());
			if("1".equals(config.getIsFans())){
				PayCoinUserForm payCoinUserForm = new PayCoinUserForm();
		    	payCoinUserForm.setCoinNum(200);
		    	payCoinUserForm.setCoinType("0");
		    	payCoinUserForm.setRemark("注册奖励");
		    	payCoinUserForm.setUserId(user.getUserId());
		    	coinUserService.savePayCoinUser(payCoinUserForm);
			}*/
			
			PayCoinUserForm payCoinUserForm = new PayCoinUserForm();
	    	payCoinUserForm.setCoinNum(400);
	    	payCoinUserForm.setCoinType("0");
	    	payCoinUserForm.setRemark("注册奖励");
	    	payCoinUserForm.setUserId(user.getUserId());
	    	coinUserService.savePayCoinUser(payCoinUserForm);
		}else{
			sysUser.setAppId(user.getAppId());
			sysUser.setUnionId(user.getUnionId());
			
			sysUser.setLat(address.getLat());
			sysUser.setLon(address.getLng());
			sysUser.setProvince(address.getProvince());
			sysUser.setCity(address.getCity());
			sysUser.setDistrict(address.getDistrict());
			if(StringUtils.isNotBlank(form.getPhone())){
				sysUser.setPhonenumber(form.getPhone());
			}
			sysUser.setWxId(user.getWxId());
			sysUser.setToken(user.getToken());
			userService.updateById(sysUser);
		}
		
		if(shareUser != null && sysUser == null){
        	// 添加朋友
            WqUserFriendForm wqUserFriendForm = new WqUserFriendForm();
            wqUserFriendForm.setUserId(Long.valueOf(form.getShareUserId()));
            wqUserFriendForm.setFriendUserId(user.getUserId());
            wqUserFriendService.insertWqUserFriend(wqUserFriendForm);
            
            userService.updateById(shareUser);
        }
		// 用户验证
        Authentication authentication = null;
        try
        {
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager
                    .authenticate(new SmsCodeAuthenticationToken(wxMaUser.getOpenId()));
        }
        catch (Exception e)
        {
            if (e instanceof BadCredentialsException)
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(wxMaUser.getNickName(), Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
                throw new UserPasswordNotMatchException();
            }
            else
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(wxMaUser.getNickName(), Constants.LOGIN_FAIL, e.getMessage()));
                throw new ServiceException(e.getMessage());
            }
        }
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(wxMaUser.getNickName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        recordLoginInfo(loginUser.getUserId());
        // 生成token
        String token = tokenService.createToken(loginUser);
        AjaxResult succes = AjaxResult.success();
        succes.put(Constants.ACCESS_TOKEN, token);
        succes.put("userId", loginUser.getUserId());
        succes.put("isWelcome", loginUser.getUser().getIsWelcome());
        
        if(StringUtils.isNotBlank(loginUser.getUser().getAppId())){
        	WxApp wxApp = wxAppService.getByAppid(loginUser.getUser().getAppId());
        	List<String> tmplIds = new ArrayList<>();
        	tmplIds.add(wxApp.getOneTemplateId());
            succes.put("tmplIds", tmplIds);
        }
        return R.ok(succes);
	}

	public R<?> wxPhone(LoginForm form) {
		WxMaForm wxMaForm = new WxMaForm();
		wxMaForm.setAppId(form.getAppId());
		wxMaForm.setCode(form.getCode());
		wxMaForm.setEncryptedData(form.getEncryptedData());
		wxMaForm.setIv(form.getIv());
		String phonenumber = wxMaUserService.getPhoneNumberInfo(wxMaForm);
		SysUser sysUser = userService.getById(SecurityUtils.getUserId());
		sysUser.setPhonenumber(phonenumber);
		userService.updateById(sysUser);
		return R.ok(phonenumber);
	}
	
	public SysUser getShare(){
		SysUser user = userService.getById(SecurityUtils.getUserId());
		if(StringUtils.isBlank(user.getQrCode())){
			WxMaForm wxMaForm = new WxMaForm();
			wxMaForm.setAppId(user.getAppId());
			String qrPath = "pages/index/share?my=true&shareUserId="+user.getUserId();
			if("1".equals(user.getIsStore())){
				qrPath = "pages/index/pay?my=true&shareUserId="+user.getUserId();
			}
			wxMaForm.setQrPath(qrPath);
			byte[] data = wxMaCodeService.createQrCode(wxMaForm);
			
			/*String qrPath = "pages/index/share";
			String scene = "my=false&shareUserId="+user.getUserId();
			wxMaForm.setQrPath(qrPath);
			wxMaForm.setScene(scene);
			byte[] data = wxMaCodeService.createQrCodeUnlimit(wxMaForm);*/
			String qrCode = OSSFactory.build().uploadSuffix(data, "jpg");
			user.setQrCode(qrCode);
			userService.updateById(user);
		}
		return user;
	}

	public R<?> dyLogin(LoginForm form) {
		DyMaForm dyMaForm = new DyMaForm();
		dyMaForm.setAppId(form.getAppId());
		dyMaForm.setCode(form.getCode());
		dyMaForm.setRawData(form.getRawData());
		dyMaForm.setAnonymousCode(form.getAnonymousCode());
		DyMaUser dyMaUser = dyMaUserService.getUserInfo(dyMaForm);
		
		Address address = AddressUtils.getAddressByIP();
		String friendId = RandomUtil.randomNumbers(11);
		// 注册用户
		SysUser user = new SysUser();
		user.setFriendId(Long.valueOf(friendId));
		user.setAppId(dyMaUser.getAppId());
		user.setOpenId(dyMaUser.getOpenId());
		user.setDeptId(100L);
		user.setNickName(dyMaUser.getNickName());
		user.setAvatar(dyMaUser.getAvatarUrl());
		user.setUserType(UserType.APP.getCode());
		user.setSex(dyMaUser.getGender());
		user.setLat(address.getLat());
		user.setLon(address.getLng());
		user.setProvince(address.getProvince());
		user.setCity(address.getCity());
		user.setDistrict(address.getDistrict());
		user.setToken(IdUtils.fastUUID());
		user = userService.saveUserByWx(user);
		
		if(StringUtils.isNotBlank(form.getShareUserId())){
        	// 添加朋友
            WqUserFriendForm wqUserFriendForm = new WqUserFriendForm();
            wqUserFriendForm.setUserId(Long.valueOf(form.getShareUserId()));
            wqUserFriendForm.setFriendUserId(user.getUserId());
            wqUserFriendService.insertWqUserFriend(wqUserFriendForm);
        }
		// 用户验证
        Authentication authentication = null;
        try
        {
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager
                    .authenticate(new SmsCodeAuthenticationToken(dyMaUser.getOpenId()));
        }
        catch (Exception e)
        {
            if (e instanceof BadCredentialsException)
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(dyMaUser.getNickName(), Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
                throw new UserPasswordNotMatchException();
            }
            else
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(dyMaUser.getNickName(), Constants.LOGIN_FAIL, e.getMessage()));
                throw new ServiceException(e.getMessage());
            }
        }
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(dyMaUser.getNickName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        recordLoginInfo(loginUser.getUserId());
        // 生成token
        String token = tokenService.createToken(loginUser);
        AjaxResult succes = AjaxResult.success();
        succes.put(Constants.TOKEN, token);
        succes.put("userId", loginUser.getUserId());
        succes.put("isWelcome", loginUser.getUser().getIsWelcome());
        
        if(StringUtils.isNotBlank(loginUser.getUser().getAppId())){
        	WxApp wxApp = wxAppService.getByAppid(loginUser.getUser().getAppId());
        	List<String> tmplIds = new ArrayList<>();
        	tmplIds.add(wxApp.getOneTemplateId());
            succes.put("tmplIds", tmplIds);
        }
        return R.ok(succes);
	}

	public void addBlack(SysUser user) {
		SysUser sysUser = userService.getById(user.getUserId());
		sysUser.setIsBlack("1");
		Date now = new Date();
		Date openTime = DateUtil.offsetDay(now, 2);
		sysUser.setOpenTime(openTime);
		userService.updateById(sysUser);
		
		// 所有动态拉黑
		wqDynamicService.addBlackByUserId(user.getUserId());
		// 封号
		userService.addBlackByUnionId(user.getUnionId());
		
		redisCache.deleteKeyPre(DynamicService.KEY_DYNAMIC);
		redisCache.deleteKeyPre(DynamicService.KEY_DYNAMIC_TOTAL);
		
		redisCache.deleteKeyPre(KEY_USER);
        redisCache.deleteKeyPre(KEY_USER_TOTAL);
	}

	public void addVisit(Long userId) {
		Integer visitNum = userVisitService.addVisit(userId);
		SysUser sysUser = userService.getById(userId);
		if(sysUser.getVisitNum() < visitNum){
			sysUser.setVisitRead("1");
			sysUser.setVisitNum(visitNum);
			userService.updateById(sysUser);
		}
	}

	public void addBlackUser(SysUser user) {
		SysUser sysUser = userService.getById(user.getUserId());
		sysUser.setIsBlack("1");
		sysUser.setStatus("1");
		userService.updateById(sysUser);
		
		// 所有动态拉黑
		wqDynamicService.addBlackUserByUserId(user.getUserId());
		// 封号
		userService.addBlackByUnionId(user.getUnionId());
		
		redisCache.deleteKeyPre(DynamicService.KEY_DYNAMIC);
		redisCache.deleteKeyPre(DynamicService.KEY_DYNAMIC_TOTAL);
		
		redisCache.deleteKeyPre(KEY_USER);
        redisCache.deleteKeyPre(KEY_USER_TOTAL);
	}

	public R<?> getPhone(LoginForm form) {
		WxMaForm wxMaForm = new WxMaForm();
		wxMaForm.setAppId(form.getAppId());
		wxMaForm.setCode(form.getCode());
		String phonenumber = wxMaUserService.getOpenPhoneNumberInfo(wxMaForm);
		return R.ok(phonenumber);
	}

	public void addImBlackUser(SysUser user) {
		
	}

	public R<?> wxLoginApp(LoginForm form) {
		WxMaForm wxMaForm = new WxMaForm();
		wxMaForm.setAppId(form.getAppId());
		wxMaForm.setCode(form.getCode());
		wxMaForm.setEncryptedData(form.getEncryptedData());
		wxMaForm.setIv(form.getIv());
		wxMaForm.setRawData(form.getRawData());
		wxMaForm.setSignature(form.getSignature());
		WxMaUser wxMaUser = wxMaUserService.getUserInfo(wxMaForm);
		
		WxApp app = wxAppService.getByAppid(wxMaUser.getAppId());
		
		Address address = AddressUtils.getAddressByIP();
		String friendId = RandomUtil.randomNumbers(11);
		// 注册用户
		SysUser user = new SysUser();
		
		SysUser otherUser = null;
		if(StringUtils.isNotBlank(wxMaUser.getUnionId()) && StringUtils.isNotBlank(app.getWxId())){
			List<SysUser> userList = userService.getUserNotNullByUnionId(app.getWxId(), wxMaUser.getUnionId());
			if(!CollectionUtils.isEmpty(userList)){
				otherUser = userList.get(0);
			}
		}
		user.setFriendId(Long.valueOf(friendId));
		user.setAppId(wxMaUser.getAppId());
		user.setOpenId(wxMaUser.getOpenId());
		user.setWxOpenId(form.getWxOpenId());
		user.setWxId(app.getWxId());
		user.setUnionId(wxMaUser.getUnionId());
		user.setDeptId(100L);
		user.setNickName(form.getNickName());
		user.setAvatar(form.getAvatar());
		SysUser randomUser = null;

		randomUser = userService.getRandomUser();
		while("微信用户".equals(randomUser.getNickName())){
			randomUser = userService.getRandomUser();
		}
		if(StringUtils.isBlank(user.getNickName())){
			user.setNickName(randomUser.getNickName());
		}else{
			WxMaForm wf = new WxMaForm();
        	wf.setAppId(user.getAppId());
        	wf.setMessage(user.getNickName());
        	wf.setOpenId(user.getOpenId());
        	Boolean checkMessage = wxMaUserService.checkMessage(wf);
        	if(!checkMessage){
        		throw new ServiceException("昵称涉嫌违规");
        	}
        	if(StringUtils.getMatch(user.getNickName())){
        		throw new ServiceException("昵称涉嫌违规");
        	}
		}
		//user.setAvatar(randomUser.getAvatar());
		
		user.setUserType(UserType.APP.getCode());
		user.setLat(address.getLat());
		user.setLon(address.getLng());
		user.setProvince(address.getProvince());
		user.setCity(address.getCity());
		user.setDistrict(address.getDistrict());
		user.setToken(IdUtils.fastUUID());
		
		SysUser sysUser = userService.selectUserByOpenId(user.getOpenId());
		SysUser shareUser = null;
		if(StringUtils.isNotBlank(form.getShareUserId())){
			shareUser = userService.getById(form.getShareUserId());
		}
		if(sysUser == null){
			user.setScene(form.getScene());
			user.setPhonenumber(form.getPhone());
			
			// 自动注册
			if(shareUser != null){
				user.setVisitUserId(shareUser.getUserId());
			}
			
			user.setIsPay("1");
			if(otherUser != null){
				user.setWxOpenId(otherUser.getWxOpenId());
				//user.setNickName(otherUser.getNickName());
				user.setIdCardStatus(otherUser.getIdCardStatus());
				//user.setAvatar(otherUser.getAvatar());
				user.setSex(otherUser.getSex());
				user.setAge(otherUser.getAge());
				//user.setWechat(otherUser.getWechat());
				user.setWechatStatus(otherUser.getWechatStatus());
				user.setAlbums(otherUser.getAlbums());
				user.setPhonenumber(otherUser.getPhonenumber());
				//user.setIsBlack(otherUser.getIsBlack());
				user.setStatus(otherUser.getStatus());
			}else{
				// 赠送10分钟体验会员
				Date vipStartTime = new Date();
				Date vipEndTime = DateUtil.offsetMinute(vipStartTime, 10);
				user.setWechatNum(1);
				user.setPublishNum(1);
				user.setVipStartTime(vipStartTime);
				user.setVipEndTime(vipEndTime);
			}
			
			userService.save(user);
			
			WqNoticeChat noticeChat = new WqNoticeChat();
			noticeChat.setFromUserId(11637079L);
			noticeChat.setToUserId(user.getUserId());
			noticeChat.setNoticeType("SYSTEM");
			noticeChat.setRemark("恭喜你注册成功！");
			wqNoticeChatService.saveOrUpdate(noticeChat);
			
			// 通过好友邀请注册，赠送趣币
			if(shareUser != null){
				/*PayCoinUserForm payCoinUserForm = new PayCoinUserForm();
		    	payCoinUserForm.setCoinNum(200);
		    	payCoinUserForm.setCoinType("0");
		    	payCoinUserForm.setRemark("邀请好友奖励");
		    	payCoinUserForm.setUserId(shareUser.getUserId());
		    	coinUserService.savePayCoinUser(payCoinUserForm);
		    	
		    	WxMpMsgForm msgForm = new WxMpMsgForm();
        		msgForm.setWxId(shareUser.getWxId());
        		msgForm.setAppId(shareUser.getAppId());
        		msgForm.setOpenId(shareUser.getWxOpenId());
        		Map<String,String> dataMap = new HashMap<>();
        		dataMap.put("first", "您好，您收到一条奖励通知");
        		dataMap.put("keyword1", "cc");
        		dataMap.put("keyword2", DateUtil.now());
        		dataMap.put("keyword3", "您好，您收到200趣豆奖励");
        		dataMap.put("remark", "本条信息是站内信通知，祝您早日脱单！点击查看详情");
        		msgForm.setDataMap(dataMap);
        		msgForm.setPage("pages/index");
        		wxMsgService.sendTemplateMsg(msgForm);*/
			}
			
			// 需要关注公众号送奖励
			SysConfig config = sysConfigService.getConfig(user.getAppId());
			if("1".equals(config.getIsFans())){
				/*PayCoinUserForm payCoinUserForm = new PayCoinUserForm();
		    	payCoinUserForm.setCoinNum(400);
		    	payCoinUserForm.setCoinType("0");
		    	payCoinUserForm.setRemark("注册奖励");
		    	payCoinUserForm.setUserId(user.getUserId());
		    	coinUserService.savePayCoinUser(payCoinUserForm);*/
			}
		}else{
			sysUser.setAppId(user.getAppId());
			sysUser.setUnionId(user.getUnionId());
			if(StringUtils.isNotBlank(user.getAvatar())){
				sysUser.setAvatar(user.getAvatar());
			}
			if(StringUtils.isNotBlank(user.getNickName())){
				sysUser.setNickName(user.getNickName());
			}
			sysUser.setLat(address.getLat());
			sysUser.setLon(address.getLng());
			sysUser.setProvince(address.getProvince());
			sysUser.setCity(address.getCity());
			sysUser.setDistrict(address.getDistrict());
			if(StringUtils.isNotBlank(form.getPhone())){
				sysUser.setPhonenumber(form.getPhone());
			}
			sysUser.setWxId(user.getWxId());
			sysUser.setToken(user.getToken());
			userService.updateById(sysUser);
		}
		
		if(shareUser != null && sysUser == null){
        	// 添加朋友
            WqUserFriendForm wqUserFriendForm = new WqUserFriendForm();
            wqUserFriendForm.setUserId(Long.valueOf(form.getShareUserId()));
            wqUserFriendForm.setFriendUserId(user.getUserId());
            wqUserFriendService.insertWqUserFriend(wqUserFriendForm);
            
            // 赠送评选机会
            shareUser.setVoteNum(1);
            userService.updateById(shareUser);
        }
		// 用户验证
        Authentication authentication = null;
        try
        {
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager
                    .authenticate(new SmsCodeAuthenticationToken(wxMaUser.getOpenId()));
        }
        catch (Exception e)
        {
            if (e instanceof BadCredentialsException)
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(wxMaUser.getNickName(), Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
                throw new UserPasswordNotMatchException();
            }
            else
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(wxMaUser.getNickName(), Constants.LOGIN_FAIL, e.getMessage()));
                throw new ServiceException(e.getMessage());
            }
        }
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(wxMaUser.getNickName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        recordLoginInfo(loginUser.getUserId());
        // 生成token
        String token = tokenService.createToken(loginUser);
        AjaxResult succes = AjaxResult.success();
        succes.put(Constants.ACCESS_TOKEN, token);
        succes.put("userId", loginUser.getUserId());
        succes.put("isWelcome", loginUser.getUser().getIsWelcome());
        succes.put("isShow", loginUser.getUser().getIsShow());
        
        if(StringUtils.isNotBlank(loginUser.getUser().getAppId())){
        	WxApp wxApp = wxAppService.getByAppid(loginUser.getUser().getAppId());
        	List<String> tmplIds = new ArrayList<>();
        	tmplIds.add(wxApp.getOneTemplateId());
            succes.put("tmplIds", tmplIds);
        }
        return R.ok(succes);
	}

	public void addVisitUser(Long userId, Long visitUserId) {
		Integer visitNum = userVisitService.addVisitUser(userId, visitUserId);
		if(visitNum != null){
			SysUser sysUser = userService.getById(userId);
			if(sysUser.getVisitNum() < visitNum){
				sysUser.setVisitRead("1");
				sysUser.setVisitNum(visitNum);
				userService.updateById(sysUser);
			}
		}
	}

	public void addUserBlack(SysUser user) {
		SysUser sysUser = userService.getById(user.getUserId());
		sysUser.setIsBlack("1");
		sysUser.setNickName("资料不通过，已被重置");
		sysUser.setSignName("资料不通过，已被重置");
		sysUser.setIntroduce("资料不通过，已被重置");
		sysUser.setProfession("资料不通过，已被重置");
		sysUser.setAvatar("http://rbtnet.oss-cn-hangzhou.aliyuncs.com/test/20240318/f14bc5cace004d0d8f202a3575721c6e.jpg");
		sysUser.setAlbums("http://rbtnet.oss-cn-hangzhou.aliyuncs.com/test/20240318/f14bc5cace004d0d8f202a3575721c6e.jpg");
		sysUser.setHobby("资料不通过，已被重置");
		sysUser.setIsWelcome(0);
		userService.updateById(sysUser);
		
		// 发送微信订阅消息
		WxMaMsgForm form = new WxMaMsgForm();
		form.setAppId(sysUser.getAppId());
		form.setOpenId(sysUser.getOpenId());
		Map<String,String> map = new HashMap<>();
		map.put("phrase1", "审核通知");
		map.put("date2", DateUtil.now());
		map.put("name3", "管理员");
		map.put("thing4", "您好，您的资料已被重置");
		form.setDataMap(map);
		form.setPage("pages/index?index=4");
		boolean flag = wxMsgService.sendSubscribeMsg(form);
		if(!flag){
			WxMpMsgForm msgForm = new WxMpMsgForm();
    		msgForm.setWxId(sysUser.getWxId());
    		msgForm.setAppId(sysUser.getAppId());
    		msgForm.setOpenId(sysUser.getWxOpenId());
    		Map<String,String> dataMap = new HashMap<>();
    		dataMap.put("first", "审核通知");
    		dataMap.put("keyword1", "管理员");
    		dataMap.put("keyword2", DateUtil.now());
    		dataMap.put("keyword3", "您好，您的资料已被重置");
    		dataMap.put("remark", "本条信息是站内信通知，祝您早日脱单！点击查看详情");
    		msgForm.setDataMap(dataMap);
    		msgForm.setPage("pages/index?index=4");
    		wxMsgService.sendTemplateMsg(msgForm);
		}
		
		// 封号
		userService.addBlackByUnionId(user.getUnionId());
		
		redisCache.deleteKeyPre(DynamicService.KEY_DYNAMIC);
		redisCache.deleteKeyPre(DynamicService.KEY_DYNAMIC_TOTAL);
		
		redisCache.deleteKeyPre(KEY_USER);
        redisCache.deleteKeyPre(KEY_USER_TOTAL);
	}

	public void addUserImBlackUser(SysUser user) {
		
	}

	public void addUserBlackUser(SysUser user) {
		SysUser sysUser = userService.getById(user.getUserId());
		sysUser.setIsBlack("1");
		sysUser.setStatus("1");
		userService.updateById(sysUser);
		
		// 所有动态拉黑
		wqDynamicService.addBlackUserByUserId(user.getUserId());
		// 封号
		userService.addBlackByUnionId(user.getUnionId());
		
		redisCache.deleteKeyPre(DynamicService.KEY_DYNAMIC);
		redisCache.deleteKeyPre(DynamicService.KEY_DYNAMIC_TOTAL);
		
		redisCache.deleteKeyPre(KEY_USER);
        redisCache.deleteKeyPre(KEY_USER_TOTAL);
	}

	public void addUserPass(SysUser user) {
		SysUser sysUser = userService.getById(user.getUserId());
		sysUser.setStatus("3");
		userService.updateById(sysUser);
	}
	
}
